home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MIDICraft's MIDINET CD-ROM
/
MIDICraft's MIDINET CD-ROM.iso
/
DOSUTILS
/
KORG
/
RECVI3.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-30
|
20KB
|
917 lines
// recvi3: (c) Günter Nagler 1996
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include "sb.hpp"
#include "korg.hpp"
#include "filei3.hpp"
#include <dir.h>
#include "korgtext.hpp"
#include <alloc.h>
Soundcard* card = 0;
char outputname[128], *outputext = 0;
unsigned char data[32000];
unsigned char *extra[4] = { 0, 0, 0, 0 };
long len = 0;
int working = 0;
int recording = 0;
int ignoring = 0;
#define request_glb 0x0e
#define send_glb 0x51
#define request_dkt 0x0d
#define send_dkt 0x52
#define request_pcg 0x1c
#define send_pcg 0x4c
#define request_sty 0x31
#define send_sty 0x65
#define request_arr 0x30
#define send_arr 0x64
#define request_bsq 0x32
#define send_bsq 0x66
#define request_sng 0x18
#define send_sng 0x48
#define request_all 0x0f
#define send_all 0x50
// other korg sysex
#define mode_change 0x4e
#define param_change 0x41
#define send_prog 0x40
#define drumkit_change 0x53
int request(Soundcard* card, int dumpmode)
{
if (!card)
return 0;
unsigned char req[6] = { 0xf0, 0x42, 0x30, 0x39, 0xFF, 0xf7 };
req[4] = dumpmode;
return card->play(req, sizeof(req)) == sizeof(req);
}
void record(unsigned char c)
{
if (len < sizeof(data))
{
data[(int)len] = c;
len++;
}
else
{
int block = (int)((len / sizeof(data))-1);
if (block >= 4)
{
len++;
return;
}
int idx = (int)(len % sizeof(data));
if (!extra[block])
{
if (idx == 0)
{
extra[block] = (unsigned char*)malloc(sizeof(data));
if (!extra[block])
{
fprintf(stderr,"not enough memory to store dump\n");
ignoring = 1;
return;
}
}
else
return;
}
extra[block][idx] = c;
len++;
}
}
unsigned char* accessdata(long i, int* n)
{
if (i < sizeof(data))
{
if (len <= sizeof(data))
*n = (int)(len-i);
else
*n = sizeof(data) - int(i);
return data + int(i);
}
else if (i < len)
{
int block = int(i / sizeof(data))-1;
int idx = (int)(i % sizeof(data));
long nexti = ((i / sizeof(data))+1) * sizeof(data);
if (len <= nexti)
*n = (int)(len-i);
else
*n = sizeof(data) - idx;
return extra[block] + idx;
}
*n = 0;
return 0;
}
int setdata(unsigned char* s, int n, long i)
{
int maxn;
int sum = 0;
while (n > 0)
{
unsigned char* code = accessdata(i, &maxn);
if (!code)
return 0;
if (maxn > n)
maxn = n;
memcpy(code, s, maxn);
s += maxn;
sum += maxn;
n -= maxn;
i += maxn;
}
return sum;
}
int getdata(unsigned char* s, int n, long i)
{
int maxn;
int sum = 0;
while (n > 0)
{
unsigned char* code = accessdata(i, &maxn);
if (!code)
return 0;
if (maxn > n)
maxn = n;
memcpy(s, code, maxn);
s += maxn;
sum += maxn;
n -= maxn;
i += maxn;
}
return sum;
}
int getword(long i)
{
unsigned char v[2];
getdata(v, 2, i);
return v[0] + (int(v[1]) << 7);
}
int savedata(FILE* f, long i, long len)
{
if (!f || i < 0 || len <= 0)
return 0;
int n;
while (len > 0)
{
unsigned char* code = accessdata(i, &n);
if (n > len)
n = (int)len;
if (fwrite(code, n, 1, f) != 1)
return 0;
i += n;
len -= n;
}
return 1;
}
long decodedata(long i, long count)
{
if (i < 0 || count <= 0 || i + count > len)
return 0;
unsigned char encoded[8];
unsigned char decoded[7];
long newi = i;
long oldi = i;
int enc, dec;
while (count > 0)
{
if (count > 8)
enc = 8;
else
enc = (int)count;
getdata(encoded, enc, i);
dec = code8to7(encoded, enc, decoded);
setdata(decoded, dec, newi);
newi += dec;
count -= enc;
i += enc;
}
/*
count = len - i;
while (count > 0)
{
if (count > 8)
enc = 8;
else
enc = (int)count;
getdata(encoded, enc, i);
setdata(encoded, enc, newi);
i+= enc;
newi+=enc;
count -= enc;
}
*/
return newi-oldi;
}
long saveglb(long pos = 5, int encoded = 1)
{
strcpy(outputext, "GLB");
FILE* f = fopen(outputname, "wb");
if (!f)
{
perror(outputname);
return 0;
}
if (encoded)
decodedata(pos, 32);
if (savedata(f, pos, 28) <= 0)
{
fprintf(stderr, "error saving global data to %s\n", outputname);
fclose(f);
return 0;
}
fprintf(stderr, "saved global data to %s\n", outputname);
fclose(f);
return encoded ? 32 : 28;
}
long savedkt(long pos = 5, int encoded = 1)
{
strcpy(outputext, "DKT");
FILE* f = fopen(outputname, "wb");
if (!f)
{
perror(outputname);
return 0;
}
if (encoded)
decodedata(5, 960);
if (savedata(f, pos, 840) <= 0)
{
fprintf(stderr, "error saving drumkit data to %s\n", outputname);
fclose(f);
return 0;
}
fprintf(stderr, "saved drumkit data to %s\n", outputname);
fclose(f);
return encoded ? 960 : 840;
}
long savepcg(long pos = 5, int encoded = 1)
{
PCGHEAD head;
memset(&head, 0, sizeof(head));
memcpy(head.korg, "KORG", 4);
head.unknown[0] = '9';
strcpy(outputext, "PCG");
FILE* f = fopen(outputname, "wb");
if (!f)
{
perror(outputname);
return 0;
}
if (encoded)
decodedata(pos, 12371);
long ofs = 0x58;
head.b1.adr = ofs; ofs += (head.b1.len = 0);
head.prognames.adr = ofs; ofs += (head.prognames.len = 10*66);
head.globals.adr = ofs; ofs += (head.globals.len = 0);
head.drumkits.adr = ofs; ofs += (head.drumkits.len = 0);
head.b5.adr = ofs; ofs += (head.b5.len = 0);
head.progdata.adr = ofs; ofs += (head.progdata.len = 164 * 66);
head.b7.adr = ofs; ofs += (head.b7.len = 0);
head.b8.adr = ofs; ofs += (head.b8.len = 0);
head.b9.adr = ofs; ofs += (head.b9.len = 0);
if (fwrite(&head, sizeof(head), 1,f) != 1)
return 0;
// program names
for (long i = pos, j = 0; j < 66; j++, i+= 164)
{
if (!savedata(f, i, 10))
return 0;
}
if (savedata(f, pos, 164*66) <= 0)
{
fprintf(stderr, "error saving program data to %s\n", outputname);
fclose(f);
return 0;
}
fprintf(stderr, "saved program data to %s\n", outputname);
fclose(f);
return encoded ? 12371 : 66*164;
}
long savesty(long pos = 5, int encoded = 1)
{
STYHEAD head;
memset(&head, 0, sizeof(head));
memcpy(head.korg, "KORG", 4);
head.unknown[0] = '9';
head.unknown[2] = 4;
head.stylenames.adr = 0x20;
head.stylenames.len = 10 * 4;
head.styletable.adr = 0x48;
head.styletable.len = sizeof(STYLINK) * 4;
strcpy(outputext, "STY");
FILE* f = fopen(outputname, "wb");
if (!f)
{
perror(outputname);
return 0;
}
STYLINK style[4];
if (encoded)
{
unsigned char buf[28];
getdata(buf, 28, pos);
int n = 28;
unsigned char* b = buf;
unsigned char* s = (unsigned char*)&style;
while (n > 0)
{
code8to7(b, n, s);
n -= 8;
b += 8;
s += 7;
}
}
else
getdata((unsigned char*)style, sizeof(style), pos);
long decsize = long(style[0].len) + long(style[1].len) +
long(style[2].len) + long(style[3].len) + 24;
long encsize = (decsize / 7) * 8 + (decsize % 7) + 1;
if (encoded)
decodedata(pos, encsize);
if (fwrite(&head, 0x20, 1,f) != 1)
return 0;
int j = 0;
for (long i = pos, k = pos+4*6; j < 4; j++, i+= 6)
{
if (!savedata(f, k, 10))
return 0;
k += style[j].len;
}
if (savedata(f, pos, decsize) <= 0)
{
fprintf(stderr, "error saving style data to %s\n", outputname);
fclose(f);
return 0;
}
fprintf(stderr, "saved style data to %s\n", outputname);
fclose(f);
return encoded ? encsize : decsize;
}
long savearr(long pos = 5, int encoded = 1)
{
ARRHEAD head;
memset(&head, 0, sizeof(head));
memcpy(head.korg, "KORG", 4);
head.unknown[0] = '9';
head.unknown[2] = 3;
head.arrnames.adr = 0x20;
head.arrnames.len = 10 * 64;
head.arrdata.adr = 0x2a0;
head.arrdata.len = 64 * 131;
strcpy(outputext, "ARR");
FILE* f = fopen(outputname, "wb");
if (!f)
{
perror(outputname);
return 0;
}
if (encoded)
decodedata(pos, 9582);
if (fwrite(&head, 0x20, 1,f) != 1)
return 0;
for (long i = pos, j = 0; j < 64; j++, i+= 131)
{
if (!savedata(f, i, 10))
return 0;
}
if (savedata(f, pos, 131*64) <= 0)
{
fprintf(stderr, "error saving arrangement data to %s\n", outputname);
fclose(f);
return 0;
}
fprintf(stderr, "saved arrangement data to %s\n", outputname);
fclose(f);
return encoded ? 9582 : 131*64;
}
long savebsq(long pos = 7, unsigned steps = 0, int encoded = 1)
{
BSQHEAD head;
memset(&head, 0, sizeof(head));
memcpy(head.korg, "KORG", 4);
head.unknown[0] = '9';
head.unknown[2] = 1;
head.unknown[3] = 1;
strcpy(outputext, "BSQ");
FILE* f = fopen(outputname, "wb");
if (!f)
{
perror(outputname);
return 0;
}
long decsize = 2292 + 16l * steps;
long encsize = (decsize / 7) * 8 + (decsize % 7) + 1;
if (encoded)
decodedata(pos, encsize);
for (long i = pos+0x79e, j = 0; j < 171; j++, i+=2)
{
unsigned v;
getdata((unsigned char*)&v, 2, i);
v += 15; // don't know why
setdata((unsigned char*)&v, 2, i);
}
if (fwrite(&head, 0x10, 1,f) != 1)
return 0;
if (savedata(f, pos, decsize) <= 0)
{
fprintf(stderr, "error saving backing sequence data to %s\n", outputname);
fclose(f);
return 0;
}
fprintf(stderr, "saved backing sequence data to %s\n", outputname);
fclose(f);
return encoded ? encsize : decsize;
}
long savesng(long pos = 7, unsigned steps = 0, int encoded = 1)
{
SNGHEAD head;
memset(&head, 0, sizeof(head));
memcpy(head.korg, "KORG", 4);
head.unknown[0] = '9';
head.unknown[1] = 1;
head.unknown[2] = 1;
strcpy(outputext, "SNG");
FILE* f = fopen(outputname, "wb");
if (!f)
{
perror(outputname);
return 0;
}
long decsize = 3702 + 16l * steps;
long encsize = (decsize / 7) * 8 + (decsize % 7) + 1;
if (encoded)
decodedata(pos, encsize);
for (long i = pos + 0xc58, j = 0; j < 271; j++, i+=2)
{
unsigned v;
getdata((unsigned char*)&v, 2, i);
v += 15; // don't know why
setdata((unsigned char*)&v, 2, i);
}
if (fwrite(&head, 0x10, 1,f) != 1)
return 0;
if (savedata(f, pos, decsize) <= 0)
{
fprintf(stderr, "error saving song data to %s\n", outputname);
fclose(f);
return 0;
}
fprintf(stderr, "saved song data to %s\n", outputname);
fclose(f);
return encoded ? encsize : decsize;
}
long saveall(long pos = 5)
{
long oldpos = pos;
unsigned bseqsteps, songsteps;
songsteps = getword(pos); pos += 2;
bseqsteps = getword(pos); pos += 2;
long declen= decodedata(pos, len-pos-1);
pos += saveglb(pos, 0);
pos += savedkt(pos, 0);
pos += savepcg(pos, 0);
pos += savearr(pos, 0);
pos += savesty(pos, 0);
pos += savesng(pos, songsteps, 0);
pos += savebsq(pos, bseqsteps, 0);
return pos-oldpos;
}
void saverecording()
{
unsigned steps = 0;
switch(data[4])
{
case send_glb:
saveglb();
break;
case send_dkt:
savedkt();
break;
case send_pcg:
savepcg();
break;
case send_sty:
savesty();
break;
case send_arr:
savearr();
break;
case send_bsq:
steps = getword(5);
savebsq(7, steps);
break;
case send_sng:
steps = getword(5);
savesng(7, steps);
break;
case send_all:
saveall();
break;
}
}
void unknownsysex()
{
if (data[1] == 0x7e && data[3] == 6 && data[4] == 2)
{
printf("identification: ");
for (int i = 0; i < len; i++)
printf(" %02X", data[i]);
printf("\n");
printf("Manufacturer id: %02X", data[5]);
int known = 0;
switch(data[5])
{
case 1: printf(" Sequential Circuits"); break;
case 2: printf(" Big Briar"); break;
case 3: printf(" Octave / Plateau"); break;
case 4: printf(" Moog"); break;
case 5: printf(" Passport Designs"); break;
case 6: printf(" Lexicon"); break;
case 0x11: printf(" PAIA"); break;
case 0x12: printf(" Simmons"); break;
case 0x13: printf(" Gentle Electric"); break;
case 0x14: printf(" Fairlight"); break;
case 0x20: printf(" Bontempi"); break;
case 0x21: printf(" S.I.E.L"); break;
case 0x23: printf(" SyntheAxe"); break;
case 0x40: printf(" Kawai"); break;
case 0x41: printf(" Roland"); break;
case 0x42: printf(" Korg"); known = 1; break;
case 0x43: printf(" Yamaha"); break;
}
printf("\n");
int v = getword(6);
printf("Family code: %02Xh ", v);
if (known && v == 0x39)
printf(" i2/i3");
else
known = 0;
printf("\n");
v = getword(8);
printf("Member code: %02Xh ", v);
if (known && v == 0)
printf(" i3");
else if (known && v == 1)
printf(" i2");
else
known = 0;
printf("\n");
v = getword(8);
printf("ROM No: %02Xh (%d)\n", v, v);
v = getword(10);
printf("Software Version: %02Xh (%d)\n", v, v);
}
else
{
printf("unknown system exclusive message ");
for (int i = 0; i < 5; i++)
printf(" %02X", data[i]);
printf(" ... F7\n");
}
}
int receivedump(int what = -1)
{
static unsigned char hearbuf[1024];
int hearlen;
unsigned char c;
int v;
unsigned steps;
card->startinput();
while (!kbhit() || getch() != 27)
{
if ((hearlen = card->hear(hearbuf, sizeof(hearbuf))) <= 0)
continue;
working = 1;
for (int i = 0; i < hearlen; i++)
{
c = hearbuf[i];
if (c == 0xf8 || c == 0xfe)
continue;
if (!recording)
{
if (c == 0xf0)
{
recording = 1;
ignoring = 0;
len = 0;
record(c);
}
continue;
}
// recording
if (len % 1000 == 0)
fprintf(stderr, "%ld\r", len);
if (len == 100)
{
if (data[1] != 0x42 || data[2] != 0x30 || data[3] != 0x39)
ignoring = 1; // unknown sysex
else if (what >= 0 && data[4] != what)
ignoring = 1;
}
if (!ignoring)
{
record(c);
}
if (c == 0xf7)
{
printf("%ld bytes received: ", len);
recording = 0;
if (data[1] != 0x42 || data[2] != 0x30)
{
unknownsysex();
if (data[1] == 0x7e && data[3] == 6 && data[4] == 2)
ungetch(27);
}
else
{
switch(data[4])
{
case send_glb:
printf("global data dump\n");
break;
case send_dkt:
printf("drumkit data dump\n");
break;
case send_pcg:
printf("all program data dump\n");
break;
case send_sty:
printf("all style data dump\n");
break;
case send_arr:
printf("all arrangement data dump\n");
break;
case send_bsq:
steps = data[5] + (data[6] << 7);
printf("all backing sequence data dump (%d steps)\n", steps);
break;
case send_sng:
steps = data[5] + (data[6] << 7);
printf("all song data dump (%d steps)\n", steps);
break;
case send_all:
printf("all data dump\n");
break;
case mode_change:
printf("mode changed to %s\n", kbdmode(data[5]));
break;
case param_change:
v = (int(data[9]) << 7) + data[8];
if (v & 0x2000)
v = v-0x4000;
printf("parameter changed in Page %d Stage %d Position %d to Value %d\n",
data[5], data[6], data[7], v);
break;
case send_prog:
unsigned char name[14];
code8to7(data+5, 8, name);
code8to7(data+5+8, 8, name+7);
printf("program data dump %-10.10s\n", name);
break;
case drumkit_change:
v = (int(data[9]) << 7) + data[8];
if (v & 0x2000)
v = v-0x4000;
printf("drumkit parameter changed in Dr%d Param %d to Value %d\n",
data[5]+1, data[6], v);
break;
default:
unknownsysex();
break;
}
}
if (!ignoring)
{
saverecording();
if (what >= 0 && data[4] == what) // finished automatically
{
hearlen = 0;
ungetch(27);
break;
}
}
}
}
}
card->stopinput();
return working != 0;
}
void checkresponse()
{
#define RETRY 100
card->startinput();
for (long i = 0; i < RETRY; i++)
if (card->hear(data, 1))
break;
if (i == RETRY)
fprintf(stderr, "Warning: no response from KORG. Transfer might not work.\n");
else
fprintf(stderr, "KORG responded\n");
card->stopinput();
}
int main(int argc, char** argv)
{
int requestid = -1;
int sendid = -1;
int identify = 0;
argc--; argv++;
while (argc > 0 && **argv == '-')
{
if (strnicmp(*argv, "-h", 2) == 0 || strcmp(*argv ,"-?") == 0)
{
printf("usage: recvi3 [-identify] [filename]\n");
printf("-identify\trequest identification of KORG i3 keyboard\n");
printf("filename\tshould have extension *,PCG,STY,ARR,SNG,BSQ,GLB,DKT\n");
printf("When no filename specified then dump must be sent manually\n");
return 1;
}
if (strnicmp(*argv, "-identify", 2) == 0)
{
identify = 1;
argc--; argv++; continue;
}
fprintf(stderr, "invalid option %s\n", *argv);
argc--; argv++;
}
if (argc > 0)
{
strcpy(outputname, *argv++); argc--;
char* ext = strrchr(outputname, '.');
if (ext)
{
ext++;
if (stricmp(ext, "glb") == 0)
{
requestid = request_glb;
sendid = send_glb;
}
else if (stricmp(ext, "dkt") == 0)
{
requestid = request_dkt;
sendid = send_dkt;
}
else if (stricmp(ext, "pcg") == 0)
{
requestid = request_pcg;
sendid = send_pcg;
}
else if (stricmp(ext, "sty") == 0)
{
requestid = request_sty;
sendid = send_sty;
}
else if (stricmp(ext, "arr") == 0)
{
requestid = request_arr;
sendid = send_arr;
}
else if (stricmp(ext, "bsq") == 0)
{
requestid = request_bsq;
sendid = send_bsq;
}
else if (stricmp(ext, "sng") == 0)
{
requestid = request_sng;
sendid = send_sng;
}
else if (stricmp(ext, "*") == 0)
{
requestid = request_all;
sendid = send_all;
}
else
fprintf(stderr, "unknown korg extenxion %s ignored\n", ext);
*ext = 0;
}
else
strcat(outputname, ".");
}
else
strcpy(outputname, "KORGI3.");
outputext = outputname + strlen(outputname);
strupr(outputname);
card = detect_soundcard();
if (!card)
{
fprintf(stderr, "Could not detect soundcard\n");
return 1;
}
checkresponse();
if (identify)
{
card->play("\xf0\x7e\x00\x06\x01\xf7", 6);
fprintf(stderr, "requesting identification\n");
requestid = -1;
sendid = -1;
}
else if (requestid >= 0)
fprintf(stderr, "requesting dump from korg\n");
else
fprintf(stderr, "waiting for receiving korg dumps. press <esc> to abort\n");
if (requestid >= 0 && !request(card, requestid))
{
fprintf(stderr, "requesting dump failed. start dump manually\n");
}
int ret = receivedump(sendid);
delete card;
return ret;
}